package com.chuangshi.core.vote.player.service.impl;

import cn.hutool.core.date.DateUtil;
import com.chuangshi.core.exception.BusinessException;
import com.chuangshi.core.kit.IdWorker;
import com.chuangshi.core.kit.Result;
import com.chuangshi.core.kit.Column;
import com.chuangshi.core.mongodb.MongodbServiceImpl;
import com.chuangshi.core.vote.member.entity.Member;
import com.chuangshi.core.vote.member.service.MemberService;
import com.chuangshi.core.vote.player.controller.admin.request.PlayerAdminV1ListRequest;
import com.chuangshi.core.vote.player.controller.mobile.request.PlayerMobileV1ListRequest;
import com.chuangshi.core.vote.player.controller.mobile.response.PlayerMobileV1FindResponse;
import com.chuangshi.core.vote.player.entity.Player;
import com.chuangshi.core.vote.player.entity.column.PlayerColumn;
import com.chuangshi.core.vote.player.service.PlayerService;
import cn.hutool.core.util.StrUtil;
import com.chuangshi.core.vote.playervote.entity.PlayerVote;
import com.chuangshi.core.vote.playervote.service.PlayerVoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 人员信息业务接口实现
 *
 * @author ggliming
 * @date 2019-02-21
 */
@Service
public class PlayerServiceImpl extends MongodbServiceImpl<Player> implements PlayerService {

    @Autowired
    private RedisTemplate<String, String> strRedisTemplate;
    @Autowired
    private MemberService memberService;
    @Autowired
    private PlayerVoteService playerVoteService;

    @Override
    public Result listForAdmin(PlayerAdminV1ListRequest request) {
        Criteria criteria = Criteria.where(Column.APP_ID).is(request.getAppId())
                        .and(Column.SYSTEM_STATUS).is(true);
        if (StrUtil.isNotBlank(request.getPlayerId())) {
            criteria.and(PlayerColumn.PLAYER_ID).regex(".*?" + request.getPlayerId() + ".*");
        }
        if (StrUtil.isNotBlank(request.getPositionId())) {
            criteria.and(PlayerColumn.POSITION_ID).is(request.getPositionId());
        }
        if (request.getPlayerNum() != null) {
            criteria.and(PlayerColumn.PLAYER_NUM).is(request.getPlayerNum());
        }
        if (StrUtil.isNotBlank(request.getPlayerName())) {
            criteria.and(PlayerColumn.PLAYER_NAME).regex(".*?" + request.getPlayerName() + ".*");
        }

        List<Sort.Order> orders = new ArrayList<Sort.Order>();
        orders.add(new Sort.Order(Sort.Direction.ASC, PlayerColumn.PLAYER_NUM));
        orders.add(new Sort.Order(Sort.Direction.DESC, PlayerColumn.PLAYER_ID));
        Sort sort = Sort.by(orders);

        Integer total = count(criteria);
        List<Player> list = list(criteria, sort, request.getPageIndex(), request.getPageSize());


        Result result = new Result();
        result.setTotal(total);
        result.setList(list);

        return result;
    }

    @Override
    public List<Player> listByPositionId(PlayerMobileV1ListRequest request) {

        Criteria criteria = Criteria.where(Column.APP_ID).is(request.getAppId())
                .and(Column.SYSTEM_STATUS).is(true)
                .and(PlayerColumn.POSITION_ID).is(request.getPositionId());

        List<Sort.Order> orders = new ArrayList<Sort.Order>();
        if (request.getSortByVoteNum() != null && request.getSortByVoteNum()) {
            orders.add(new Sort.Order(Sort.Direction.DESC, PlayerColumn.PLAYER_VOTE_NUM));
            orders.add(new Sort.Order(Sort.Direction.ASC, PlayerColumn.PLAYER_NUM));
        } else {
            orders.add(new Sort.Order(Sort.Direction.ASC, PlayerColumn.PLAYER_NUM));
        }
        Sort sort = Sort.by(orders);
        return list(criteria, sort);
    }

    @Override
    public PlayerMobileV1FindResponse voting(String playerId, String memberId, String appId) {

        Player player = this.find(playerId);
        if (player == null) {
            throw new BusinessException("数据不存在");
        }
        Member member = memberService.find(memberId);
        if (member == null) {
            throw new BusinessException("请先登陆");
        }

        String realKey = "vote_date:" + DateUtil.format(new Date(), "yyyy-MM-dd") + ":" + memberId;
        String value = strRedisTemplate.opsForValue().get(realKey);
        if (StrUtil.isEmpty(value)) {
            strRedisTemplate.opsForValue().set(realKey, "1", 24 * 3600, TimeUnit.SECONDS);
        } else {
            Long increment = strRedisTemplate.opsForValue().increment(realKey);
            if (increment >= 6) {
                throw new BusinessException("每人每天只能投5票，请第二天再来吧");
            }
        }

        int voteNum = player.getPlayerVoteNum() != null ? player.getPlayerVoteNum() + 1 : 1;
        player.setPlayerVoteNum(voteNum);
        Boolean result = this.update(player, player.getSystemVersion());
        if (!result) {
            strRedisTemplate.opsForValue().decrement(realKey);
            throw new BusinessException("网络异常，请重试");
        }

        PlayerVote vote = new PlayerVote();
        vote.setPlayerVoteId(IdWorker.getIdStr());
        vote.setMemberId(memberId);
        vote.setPlayerId(playerId);
        vote.setPlayerName(player.getPlayerName());
        vote.setPositionName(player.getPositionName());
        vote.setAppId(appId);
        playerVoteService.save(vote);
        PlayerMobileV1FindResponse response = new PlayerMobileV1FindResponse();
        response.setPlayerImagePath(player.getPlayerImagePath());
        response.setPlayerName(player.getPlayerName());
        response.setPlayerVoteNum(voteNum);
        response.setPositionId(player.getPositionId());

        return response;
    }

    @Override
    public List<Player> listAll() {
        Criteria criteria = Criteria.where(Column.APP_ID).is("1098410044304789504")
                .and(Column.SYSTEM_STATUS).is(true);

        List<Sort.Order> orders = new ArrayList<Sort.Order>();
        orders.add(new Sort.Order(Sort.Direction.ASC, PlayerColumn.POSITION_ID));
        orders.add(new Sort.Order(Sort.Direction.DESC, PlayerColumn.PLAYER_VOTE_NUM));
        orders.add(new Sort.Order(Sort.Direction.ASC, PlayerColumn.PLAYER_NUM));

        Sort sort = Sort.by(orders);
        return list(criteria, sort);
    }
}